package com.yugao.fintech.antelope.codegen.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yugao.fintech.antelope.codegen.assembly.DatasourceConfigAssembly;
import com.yugao.fintech.antelope.codegen.core.GeneratorConfig;
import com.yugao.fintech.antelope.codegen.core.SQLService;
import com.yugao.fintech.antelope.codegen.core.SQLServiceFactory;
import com.yugao.fintech.antelope.codegen.core.TableDefinition;
import com.yugao.fintech.antelope.codegen.manager.DatasourceConfigManager;
import com.yugao.fintech.antelope.codegen.manager.GenTableColumnManager;
import com.yugao.fintech.antelope.codegen.manager.GenTableIndexManager;
import com.yugao.fintech.antelope.codegen.manager.GenTableManager;
import com.yugao.fintech.antelope.codegen.model.entity.DatasourceConfig;
import com.yugao.fintech.antelope.codegen.model.entity.GenTable;
import com.yugao.fintech.antelope.codegen.model.rqrs.DatasourceConfigQuery;
import com.yugao.fintech.antelope.codegen.model.rqrs.DatasourceRS;
import com.yugao.fintech.antelope.codegen.model.rqrs.DbTableRQ;
import com.yugao.fintech.antelope.codegen.service.DatasourceConfigService;
import com.yugao.fintech.framework.assistant.utils.exception.BizException;
import com.yugao.fintech.framework.core.page.PageModel;
import com.yugao.fintech.framework.core.page.TableSupport;
import com.yugao.fintech.framework.desensitization.annotations.FieldBindHandle;
import com.yugao.fintech.framework.mybatisplus.utils.PageUtil;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.regex.Pattern;
import java.util.stream.Collectors;


@Service
@RequiredArgsConstructor
public class DatasourceConfigServiceImpl implements DatasourceConfigService {
    private final DatasourceConfigManager datasourceConfigManager;
    private final GenTableIndexManager genTableIndexManager;
    private final GenTableColumnManager genTableColumnManager;
    private final GenTableManager genTableManager;
    private final DatasourceConfigAssembly datasourceConfigAssembly;

    @Override
    public DatasourceConfig getById(Long id) {
        return datasourceConfigManager.getById(id);
    }

    @Override
    public List<DatasourceRS> listAll() {
        LambdaQueryWrapper<DatasourceConfig> queryWrapper = Wrappers.<DatasourceConfig>lambdaQuery()
                .orderByDesc(DatasourceConfig::getUpdatedAt);
        List<DatasourceConfig> list = datasourceConfigManager.list(queryWrapper);
        return list.stream().map(datasourceConfigAssembly::toDatasourceRS).collect(Collectors.toList());
    }

    @Override
    public void save(DatasourceConfig datasourceConfig) {
        if (!datasourceConfigManager.save(datasourceConfig)) {
            throw new BizException("保存失败");
        }
    }

    @Override
    public void update(DatasourceConfig datasourceConfig) {
        if (!datasourceConfigManager.updateById(datasourceConfig)) {
            throw new BizException("更新失败");
        }
    }

    @Override
    @Transactional
    public void delete(DatasourceConfig datasourceConfig) {
        List<GenTable> genTableList = genTableManager.listByDatasourceId(datasourceConfig.getId());
        if (!genTableList.isEmpty()) {
            List<Long> tableIds = genTableList.stream().map(GenTable::getId).collect(Collectors.toList());
            genTableManager.removeByIds(tableIds);
            genTableIndexManager.deleteBatchByTableIds(tableIds);
            genTableColumnManager.deleteBatchByTableIds(tableIds);
        }
        if (!datasourceConfigManager.removeById(datasourceConfig)) {
            throw new BizException("删除失败");
        }
    }

    @Override
    @FieldBindHandle
    public IPage<DatasourceConfig> page(DatasourceConfigQuery rq) {
        PageModel pageModel = TableSupport.buildPageRequest();
        LambdaQueryWrapper<DatasourceConfig> queryWrapper = Wrappers.<DatasourceConfig>lambdaQuery()
                .eq(Objects.nonNull(rq.getDbType()), DatasourceConfig::getDbType, rq.getDbType())
                .like(com.yugao.fintech.framework.assistant.utils.StringUtils.isNotEmpty(rq.getName()), DatasourceConfig::getName, rq.getName())
                .orderByDesc(DatasourceConfig::getUpdatedAt);
        return datasourceConfigManager.page(PageUtil.to(pageModel), queryWrapper);
    }

    @Override
    public List<TableDefinition> listTable(DbTableRQ rq) {
        DatasourceConfig dataSourceConfig = datasourceConfigManager.getById(rq.getDatasourceId());
        GeneratorConfig generatorConfig = GeneratorConfig.build(dataSourceConfig);
        SQLService service = SQLServiceFactory.build(generatorConfig);
        // 筛选表
        if (StringUtils.isNotEmpty(rq.getTableName())) {
            Pattern pattern = Pattern.compile(".*" + rq.getTableName() + ".*");
            return service.getTableSelector(generatorConfig).getSimpleTableDefinitions()
                    .stream().filter(x -> pattern.matcher(x.getTableName()).matches()).collect(Collectors.toList());
        } else {
            return service.getTableSelector(generatorConfig).getSimpleTableDefinitions();
        }
    }

    @Override
    public void deleteBatchByIds(List<Long> ids) {
        datasourceConfigManager.removeByIds(ids);
    }
}
